package com.edianping.thread;

import java.util.HashSet;
import java.util.Set;

import org.apache.log4j.Logger;

//import com.edianping.algorithm.AlgorithmProduct;
import com.daguu.lib.httpsqs4j.HttpsqsClient;
import com.daguu.lib.httpsqs4j.HttpsqsStatus;
import com.edianping.algorithm.AlgorithmProduct;
import com.edianping.bean.ProcessItemBean;
import com.edianping.bean.ProductItemBean;
import com.edianping.config.ProcessThreadConfigBean;
import com.edianping.store.ProductDBStore;
import com.edianping.util.TaskType;

/**
 * This class is the main calculate class
 * All the business logic put here
 * 
 * invoke the corresponding algorithm according to process type.
 * 
 * @author Jensen
 *
 */
public class ProductScoreProcessThread implements Runnable {
	HttpsqsClient client = null;
	private ProcessThreadConfigBean config;
	private boolean isrunning = true;
	private int minProductProcessReviewCount = 3;
	
	private AlgorithmProduct algorithnProduct = new AlgorithmProduct();

	private static Logger log = Logger.getLogger(ProductScoreProcessThread.class);
	
	public ProductScoreProcessThread( HttpsqsClient client,
			ProcessThreadConfigBean config, int minProductProcessReviewCount) {
		this.client = client;
		this.config = config;
		this.minProductProcessReviewCount = minProductProcessReviewCount;
	}

	public void run() {
		try {
			log.info("Start " + Thread.currentThread().getName());

			while ( isrunning ) {
				HttpsqsStatus status = client.getStatus( TaskType.PRODUCT_SCORE );
				if( status.unreadNumber >0 ){
					//get all product_ids, and merge them
					//put all product_id to set 
					Set<Integer> ids = new HashSet<Integer>();
					for(int i=0; i<status.unreadNumber; i++ ){
						String strData = client.getString( TaskType.PRODUCT_SCORE );
						log.info( Thread.currentThread().getName()+": get content, "+ strData );
						ids.add( Integer.parseInt( strData.trim() ) );
						
					}
					//foreach product_id, update its score, and update to database
					for( int id : ids ){
						ProcessItemBean item = ProductDBStore.GetProductInfoById( id );
						log.info( Thread.currentThread().getName()+": processing " + item.getId() );
						
						if( ((ProductItemBean)item.getBean()).getReviews().size() >= this.minProductProcessReviewCount ){
							ProcessItemBean newItem = new ProcessItemBean( item.getId() );
							
							ProductItemBean sbean = new ProductItemBean( item.getId() );
							newItem.setBean( sbean );
							((ProductItemBean)newItem.getBean()).setScore( algorithnProduct.calculateScore( ((ProductItemBean)item.getBean()).getReviews() ) );
							((ProductItemBean)newItem.getBean()).setRate( algorithnProduct.calculateRate( ((ProductItemBean)item.getBean()).getReviews() ) );
							((ProductItemBean)newItem.getBean()).setReality( algorithnProduct.calculateReality( ((ProductItemBean)item.getBean()).getReviews() ) );
							((ProductItemBean)newItem.getBean()).setService( algorithnProduct.calculateService( ((ProductItemBean)item.getBean()).getReviews() ) );
							((ProductItemBean)newItem.getBean()).setVelocity( algorithnProduct.calculateVelocity( ((ProductItemBean)item.getBean()).getReviews() ) );
							
							ProductDBStore.UpdateProductInfo( newItem );
							
							log.info( Thread.currentThread().getName()+": successfully processed product "+ item.getId() );
						}
						else{
							log.info( Thread.currentThread().getName()+": ignore product item "+ item.getId() +"as its review count is not sufficient" );
						}
					}
				}
				else{
					log.info( Thread.currentThread().getName()+": no item to process" );
					Thread.sleep( this.config.getSleepperiod() );
				}
			}
		} catch (Exception e) {
			log.error(Thread.currentThread().getName(), e );
		}
	}
	
}
